package com.heima.admin.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsScanService;
import com.heima.article.feign.ApArticleFeign;
import com.heima.article.feign.ApAuthorFeign;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.constants.MQConstants;
import com.heima.common.dtos.PageInfo;
import com.heima.common.dtos.PageRequestDto;
import com.heima.common.dtos.Result;
import com.heima.common.exception.AppHttpCodeEnum;
import com.heima.common.exception.LeadNewsException;
import com.heima.common.fastdfs.FastDFSClientUtil;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.admin.pojos.AdSensitive;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsVo;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.JsonUtils;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.feign.WmNewsFeign;
import io.seata.spring.annotation.GlobalTransactional;
import net.minidev.json.JSONUtil;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class WemediaNewsScanServiceImpl implements WemediaNewsScanService {
    @Autowired
    private WmNewsFeign wmNewsFeign;
    @Autowired
    private FastDFSClientUtil clientUtil;
    @Value("${fileServerUrl}")
    private String fileServerUrl;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private GreenImageScan greenImageScan;
    @Autowired
    private AdSensitiveMapper adSensitiveMapper;
    @Autowired
    private ApAuthorFeign apAuthorFeign;
    @Autowired
    private AdChannelMapper adChannelMapper;
    @Autowired
    private ApArticleFeign apArticleFeign;
    @Autowired
    private KafkaTemplate kafkaTemplate;


    @Override
    @GlobalTransactional
    public void autoScanByMediaNewsId(Integer id) {
        //1.根据ID查询自媒体文章
        WmNews wmNews = wmNewsFeign.findOne(id).getData();
        if (wmNews == null) return;
        //2.判断只有状态为"提交审核"才进入审核流程
        if (!WmNews.Status.SUBMIT.getCode().equals(wmNews.getStatus())) return;
        //3.提取文章的文本内容
        List<String> textList = getTextFromContent(wmNews);
        //4.提取文章的图片内容
        List<byte[]> imageList = getImageFromContent(wmNews);
        //5.提交文本内容到阿里云进行检测，根据反馈结果，修改文章的状态
        try {
            Map<String, String> result = greenTextScan.greeTextScan(textList);
            boolean flag = handlerScanResult(result, wmNews);
            if (!flag) return;


        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadNewsException(500, "调用阿里云API失败 {}" + e.getMessage());
        }

        //6.提交图片内容到阿里云进行检测，根据反馈结果，修改文章的状态
        try {
            Map result = greenImageScan.imageScan(imageList);
            boolean flag = handlerScanResult(result, wmNews);
            if (!flag) return;
        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadNewsException(500, "调用阿里云API失败");
        }

        //7.判断文本内容是否包含敏感词
        boolean flag = handlerSensitive(textList, wmNews);
        if (!flag) return;

        //判断发布时间是否大于当前时间，修改文章的状态（改为8）
        publishArticle(wmNews);
        //9.保存文章数据到App文章表中，修改文章状态为9
    }

    /**
     * 查询待审核文章
     */
    @Override
    public Result<PageInfo<WmNewsVo>> findNews(PageRequestDto<WmNews> dto) {
        return wmNewsFeign.searchNewsByCondition(dto);


    }

    /**
     * 查询审核文章详情
     */
    @Override
    public Result<WmNews> findOne(Integer id) {
        return wmNewsFeign.findOne(id);
    }

    /**
     * 审核文章
     */
    @Override
    public Result manualScan(NewsAuthDto dto, int type) {
        WmNews wmNews = wmNewsFeign.findOne(dto.getId()).getData();
        if (wmNews == null){
            throw new LeadNewsException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        try {
            if (type == 0 ){
                wmNews.setStatus(WmNews.Status.FAIL.getCode());
                wmNews.setReason(dto.getMsg());
                wmNewsFeign.update(wmNews);
            }else {
                publishArticle(wmNews);
            }
            return Result.ok();
        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadNewsException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }
    /**
     * 文章定时发布
     */
    @Override
    public void schedulePublishNews() {
        List<WmNews>wmNews = wmNewsFeign.findRelease().getData();
        if (CollectionUtils.isNotEmpty(wmNews)){
            wmNews.forEach(news ->{
                saveApArticle(news);
            });
        }
    }

    /**
     * 判断发布时间，以及发布文章
     *
     * @param wmNews
     */
    private void publishArticle(WmNews wmNews) {
        //判断发布时间是否大于当前时间，修改文章的状态（改为8）
        if (wmNews.getPublishTime().after(new Date())) {
            wmNews.setStatus(WmNews.Status.SUCCESS.getCode());
            wmNews.setReason("待发布");
            wmNewsFeign.update(wmNews);
            return;
        }
        //发表文章（保存App文章相关表数据，导入ES）
        saveApArticle(wmNews);

    }

    /**
     * 发表文章（保存App文章相关表数据，导入ES）
     *
     * @param wmNews
     */
    private void saveApArticle(WmNews wmNews) {

        //保存ApArticle
        ApArticle apArticle = new ApArticle();
        apArticle.setTitle(wmNews.getTitle());

        //查询并设置作者信息
        ApAuthor apAuthor = apAuthorFeign.findApAuthorByWmUserId(wmNews.getUserId()).getData();
        if (apAuthor != null) {
            apArticle.setAuthorId(apAuthor.getId());
            apArticle.setAuthorName(apAuthor.getName());
        }
        //查询并设置频道信息
        AdChannel adChannel = adChannelMapper.selectById(wmNews.getChannelId());
        if (adChannel != null) {
            apArticle.setChannelId(adChannel.getId());
            apArticle.setChannelName(adChannel.getName());
        }
        apArticle.setLayout(wmNews.getType());
        apArticle.setFlag(0);
        apArticle.setImages(wmNews.getImages());
        apArticle.setLabels(wmNews.getLabels());
        apArticle.setLikes(0);
        apArticle.setCollection(0);
        apArticle.setComment(0);
        apArticle.setViews(0);
        apArticle.setCreatedTime(new Date());
        apArticle.setPublishTime(wmNews.getPublishTime());

        apArticle = apArticleFeign.saveApArticle(apArticle).getData();

        //保存ApArticleConfig
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(apArticle.getId());
        apArticleConfig.setIsComment(1);
        apArticleConfig.setIsForward(1);
        apArticleConfig.setIsDown(0);
        apArticleConfig.setIsDelete(0);

        apArticleFeign.saveApArticleConfig(apArticleConfig);

        //保存ApArticleContent
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(wmNews.getContent());

        apArticleFeign.saveApArticleContent(apArticleContent);

        //修改自媒体文章的信息
        wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
        wmNews.setReason("发布成功");
        wmNews.setArticleId(apArticle.getId());//关联已经发布的文章ID
        wmNewsFeign.update(wmNews);

        //TODO 文章同步到ES索引库
        kafkaTemplate.send(MQConstants.WM_NEW_UP_ES_TOPIC,apArticle.getId()+"");
    }


    /**
     * 检测敏感词
     *
     * @param textList
     * @param wmNews
     */
    private boolean handlerSensitive(List<String> textList, WmNews wmNews) {
        boolean flag = false;

        List<AdSensitive> adSensitives = adSensitiveMapper.selectList(null);

        List<String> wordList = adSensitives.stream().map(AdSensitive::getSensitives).collect(Collectors.toList());
        SensitiveWordUtil.initMap(wordList);
        if (CollectionUtils.isNotEmpty(textList)) {
            String collect = textList.stream().collect(Collectors.joining(""));
            Map<String, Integer> result = SensitiveWordUtil.matchWords(collect);
            if (result.size() == 0) {
                flag = true;
            }
        }
        if (!flag) {
            wmNews.setStatus(WmNews.Status.FAIL.getCode());
            wmNews.setReason("包含违规的敏感词");
            wmNewsFeign.update(wmNews);
        }
        return flag;

    }

    /**
     * 处理阿里云的反馈结果
     *
     * @param result
     * @param wmNews
     * @return
     */

    private boolean handlerScanResult(Map<String, String> result, WmNews wmNews) {
        String suggestion = result.get("suggestion");
        boolean flag = false;
        if (StringUtils.isNotEmpty(suggestion)) {
            if ("pass".equals(suggestion)) {
                flag = true;
            }
            if ("review".equals(suggestion)) {
                wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode());
                wmNews.setReason("待人工审核");
                wmNewsFeign.update(wmNews);
            }
            if ("block".equals(suggestion)) {
                wmNews.setStatus(WmNews.Status.FAIL.getCode());
                wmNews.setReason("云检测失败");
                wmNewsFeign.update(wmNews);
            }
        }
        return flag;
    }

    /**
     * 提取文章中图片
     *
     * @param wmNews
     * @return
     */
    private List<byte[]> getImageFromContent(WmNews wmNews) {
        ArrayList<byte[]> imageList = new ArrayList<>();
        //提取内容的图片
        if (StringUtils.isNotEmpty(wmNews.getContent())) {

            List<Map<String, String>> list = JsonUtils.toBean(wmNews.getContent(), List.class);

            for (Map<String, String> map : list) {
                if (map.get("type").equals("image")) {
                    String url = map.get("value");
                    imageList.add(downImageFromFdfs(url));
                }
            }
        }
        //提取封面的图片
        if (StringUtils.isNotEmpty(wmNews.getImages())) {
            String[] images = wmNews.getImages().split(",");
            for (String url : images) {
                imageList.add(downImageFromFdfs(url));
            }
        }
        return imageList;

    }

    /**
     * 通过url下载FastDFS的图片
     */
    private byte[] downImageFromFdfs(String url) {
        url = url.replaceAll(fileServerUrl, "");//   group1/M00/00/00/wKhChWEJoiqAUqsLAAEGTWC84Nw97.jpeg

        String grouName = url.substring(0, url.indexOf("/"));
        String path = url.substring(grouName.length() + 1);
        try {
            byte[] imageBytes = clientUtil.download(grouName, path);
            return imageBytes;
        } catch (IOException e) {
            e.printStackTrace();
            throw new LeadNewsException(500, "图片下载失败");
        }


    }

    /**
     * 提取文本内容
     *
     * @param wmNews
     * @return
     */
    private List<String> getTextFromContent(WmNews wmNews) {
        ArrayList<String> textList = new ArrayList<>();
        //提取文本
        if (StringUtils.isNotEmpty(wmNews.getContent())) {
            List<Map<String, String>> list = JsonUtils.toBean(wmNews.getContent(), List.class);
            for (Map<String, String> map : list) {
                if (map.get("type").equals("text")) {
                    textList.add(map.get("value"));
                }
            }
        }

        textList.add(wmNews.getTitle());
        return textList;
    }
}
